<?php
require_once 'CSV.php';
class Database
{
    public static $db;

    public function connect()
    {
    	$timezone_identifier = 'UTC';
    	date_default_timezone_set($timezone_identifier);
    	$credentials = $this->getCredentials();
    	$dsn = CSV::Read($credentials, 'dsn');
    	$user =  CSV::Read($credentials, 'user');
   		$password = CSV::Read($credentials, 'password');

   		try {
                    self::$db = new PDO($dsn[0][1], $user[0][1], $password[0][1]);
   		} catch (PDOException $ee) {
    		throw $ee;
    	}
    }

    /* return the string contents of the configuration file.
     * The file is expected to contain 3 lines to be used to initialize the database
    * dsn,mysql:dbname=theDBname;host=127.0.0.1
    * user,sql_user_name
    * password,thepassword
    */
    private function getCredentials()
    {
    	//My server is an amazon server. I'm able to use the server software variable to distinguish
    	//it from my development environment.  This makes development faster since I don't have to be
    	//careful about which files I copy to the server.
    	$serverInfo = $_SERVER['SERVER_SOFTWARE'];
    	if (strstr($serverInfo, 'Amazon')) {
            //the path to use on the production server
            $filePath = '/var/www/airIdentityCredentials.txt';
        } else {
            //a different path for use on the development machine (the path where THIS file resides)
            $filePath = 'airIdentityCredentials.txt';
        }
        $fileContents = file_get_contents($filePath);
        return $fileContents;
    }
    
    /*
     * log an event to the EventLog table
    */
    public function logEvent($source, $level, $description)
    {
        $address = $_SERVER['REMOTE_ADDR'];
    	$sql = 'call LogEvent(?,?,?,?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $source);
    	$prepared->bindParam(2, $level);
    	$prepared->bindParam(3, $description);
    	$prepared->bindParam(4, $address);
    	$prepared->execute();
    }
    
    public function aesEncrypt($clearText, $userName)
    {
    	$this->logEvent('Database->aesEncrypt', 50, 'AesEncrypt called for ' .
                $userName . ', encrypting ' . $clearText);
        $sql = 'call AesEncrypt(?,?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $clearText);
    	$prepared->bindParam(2, $userName);
    	$prepared->execute();
    	$result = ''; //this line is here to clear a compiler warning that $result is not initialized.
    	$prepared->bindColumn(1,$result);
    	$prepared->fetch();
        $this->logEvent(__METHOD__, 52, 'result for ' . $userName . '\'s request is: ' . $result);
        return $result;
    }

    public function aesDecrypt($encrypted, $userName)
    {
    	$this->logEvent('Database->aesDecrypt', 50, 'AesDecrypt called for ' .
                $userName . ', decrypting ' . $encrypted);
        $sql = 'call AesDecrypt(?,?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $encrypted);
    	$prepared->bindParam(2, $userName);
    	$prepared->execute();
    	$result = ''; //this line is here to clear a compiler warning that $result is not initialized.
    	$prepared->bindColumn(1,$result);
    	$prepared->fetch();
    	return $result;
    }

    public function getLogEntry($source)
    {
    	$sql = 'call GetLogEntry(?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $source);
    	$prepared->execute();
    	//$result = ''; //this line is here to clear a compiler warning that $result is not initialized.
    	return $prepared->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /*
     * REturn log entries that meet the given criteria
     */
    public function getLogEntries($lessOrEqual, $level, $method = '')
    {
        $sql = 'call GetLogEntries(?, ?, ?)';
        $prepared = self::$db->prepare($sql);
        $prepared->bindParam(1, $lessOrEqual);
        $prepared->bindParam(2, $level);
        $prepared->bindParam(3, $method);
		$prepared->execute();
		return $prepared->fetchAll(PDO::FETCH_ASSOC);
    }
    
    public function getLastNEntries($n){
        $sql = 'call GetLastNEntries(?)';
        $prepared = self::$db->prepare($sql);
        $prepared->bindParam(1, $n);
        $prepared->execute();
        return $prepared->fetchAll(PDO::FETCH_ASSOC);
    }
    /*
     * GetNonce returns the current nonce value for the given user.
     * It also updates the 'used' field on the nonce which is used in 
     * generating a subsequent nonce
     */
    public function getNonce($userName)
    {
    	$sql = 'call GetNonce(?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $userName);
    	$prepared->execute();
    	$result = ''; //this line is here to clear a compiler warning that $result is not initialized.
    	$prepared->bindColumn(1,$result);
    	$prepared->fetch();
    	return $result;
    }

    public function getTimeStamp($userName)
    {
    	$sql = 'call GetTimeStamp(?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $userName);
    	$prepared->execute();
    	$result = ''; //this line is here to clear a compiler warning that $result is not initialized.
    	$prepared->bindColumn(1,$result);
    	$prepared->fetch();
    	return $result;
    }
    /*
     * GetNonce returns the current nonce value for the given user.
    * It also updates the 'used' field on the nonce which is used in
    * generating a subsequent nonce
    */
    public function getClientNonce($userName)
    {
    	$sql = 'call GetClientNonce(?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $userName);
    	$prepared->execute();
    	$result = ''; //this line is here to clear a compiler warning that $result is not initialized.
    	$prepared->bindColumn(1,$result);
    	$prepared->fetch();
    	return $result;
    }

    public function getKeys($userName)
    {
        $sql = 'call getKeys(?)';
        $prepared = self::$db->prepare($sql);
    	$prepared->execute(array($userName));
        $userResults = $prepared->fetchAll(PDO::FETCH_ASSOC);
        return $userResults;
    }
    
    public function insertUser($userName, $privateKey, $publicKey, $secretKey)
    {
            $sql = 'call insertUser(?,?,?,?)';
            $prepared = self::$db->prepare($sql);
            $prepared->bindParam(1, $userName);
            $prepared->bindParam(2, $privateKey);
            $prepared->bindParam(3, $publicKey);
            $prepared->bindParam(4, $secretKey);
            $prepared->execute(); 
    }

    public function getPermission($userName, $resourceName)
    {
            $sql = 'call GetPermission (? , ?)';
            $prepared = self::$db->prepare($sql);
            $success = $prepared->execute(array($userName, $resourceName));
            $permissionResults = $prepared->fetchAll(PDO::FETCH_ASSOC);
            return $permissionResults;
    }
    
    /*
     * Get a configuration item with the given tag name from the database Configuration table
    */
    public function getConfiguration($tag)
    {
    	$sql = 'call GetConfiguration(?)';
    	$prepared = self::$db->prepare($sql);
    	$prepared->bindParam(1, $tag);
    	$prepared->execute();
    	$result = $prepared->fetch(PDO::FETCH_ASSOC);
    	return $result['contents'];
    }
    
    public function toMySqlDate($ymdHisString)
    {
    	return date('Y-m-d H:i:s', $ymdHisString);
    }
    
    public function toPhpDate($mySqlDate)
    {
    	return strtotime($mySqlDate);
    }
}
?>